#include <sys/param.h>
#include <pwd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <crypt.h>
#include <security/pam_modules.h>
#include <security/pam_appl.h>
#include <shadow.h>

static char password_prompt[] = "Password :";

PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags,
		    int argc, const char *argv[])
{
  struct pam_conv *conv;
  struct pam_message msg;
  const struct pam_message *msgp;
  struct pam_response *resp;
  struct passwd *pwd;
  const char *user;
  char *password, *password_new;
  int pam_err, retry, output_len, key_size, outlen;
  long size, newPrivSize, newPubSize;

  /* identify user */
  if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
    return (pam_err);
 
  printf("The user name entered is %s \n",user);
  
  if (user == NULL || *user == '\0') {
    return PAM_USER_UNKNOWN;
  }


  const void *user1;
  const void *target_user;
  pam_err = pam_get_item(pamh, PAM_USER, &target_user);
  if (pam_err != PAM_SUCCESS)
    return (PAM_SYSTEM_ERR);

  fprintf(stderr, "in pam_sm_autnenticat: The target user name is %s",(const char*) target_user);

  pam_err = pam_get_item(pamh, PAM_RUSER, &user1);
  if (pam_err != PAM_SUCCESS)
    return (PAM_SYSTEM_ERR);

  fprintf(stderr, "in : The current user name is %s",(const char*) user1);










  /* Get the conversation function defined in the application */
  pam_err = pam_get_item(pamh, PAM_CONV, (const void **)&conv);
  if (pam_err != PAM_SUCCESS)
    return (PAM_SYSTEM_ERR);
  
  /* prompt the user for the password */
  msg.msg_style = PAM_PROMPT_ECHO_OFF;
  msg.msg = password_prompt;
  msgp = &msg;
  
  resp = NULL;
  pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr);
  if (resp != NULL) {
    if (pam_err == PAM_SUCCESS)
      password = resp->resp;
    else
      free(resp->resp);
  }

  /* TODO : Need to authenticate the user and retrieve the list of capability strings for that user 
   * Write the user name and password to the user's factotum which will authenticate to the host owner's
   * factotum. Once the list of capabilities is retrieved save it using pam_set_data() so that it can be
   * retrieved in pam_sm_setcred() function 
  */

  return PAM_SUCCESS;
}

PAM_EXTERN int
pam_sm_setcred(pam_handle_t *pamh, int flags,
	       int argc, const char *argv[])
{
  int i, pam_err;
  printf(" inside the pam_sm_setcred function \n");
  printf(" argc : %d", argc);

  for(i=0; i< argc; i++)
    printf("i: %d name :  %s \n", i, argv[i]);
  
  if (flags & PAM_DELETE_CRED)
    fprintf(stderr, "PAM_DELETE_CRED");

  if (flags & PAM_REFRESH_CRED)
    fprintf(stderr, "PAM_REFRESH_CRED");

  if (flags & PAM_REINITIALIZE_CRED)
    fprintf(stderr, "PAM_REINITSILAISE_CRED");

  if (flags & PAM_ESTABLISH_CRED)
    //  return (PAM_SERVICE_ERR);
    fprintf(stderr, "PAM_ESTABLISH_CRED");

  const void *user;
  const void *target_user;
  pam_err = pam_get_item(pamh, PAM_USER, &target_user);
  if (pam_err != PAM_SUCCESS)
    return (PAM_SYSTEM_ERR);

  fprintf(stderr, "The target user name is %s",(const char*) target_user);

  pam_err = pam_get_item(pamh, PAM_RUSER, &user);
  if (pam_err != PAM_SUCCESS)
    return (PAM_SYSTEM_ERR);

  fprintf(stderr, "The current user name is %s",(const char*) user);

  /* TODO : Check if a capability exists for this target user - if 
   * yes then use that by writing it to /dev/capuse.
   * Once written the user id of the process would change to that of the target user
   * If there is no capability found then return PAM_SYSTEM_ERROR
   */



  return (PAM_SUCCESS);
}


